﻿namespace MineSweeperCheater
{
  public class Cheater
  {
    public struct FieldDimensions
    {
      public int Rows;
      public int Cols;
    };

    public static string[] GenerateCheat(string[] mineField)
    {
      var mineFieldDimensions = DetermineMineFieldDimensions(mineField);
      var cheatFieldDimensions = mineFieldDimensions;

      var upsizedCheatFieldDimensions = ResizeCheatFieldDimensions(cheatFieldDimensions, 2, 2);
      var upsizedCheatField = CreateEmptyCheatField(upsizedCheatFieldDimensions);

      AnalyzeMineField(mineField, ref upsizedCheatField);

      var cheatFieldStringArray = new string[cheatFieldDimensions.Rows];
      TransformCheatFieldToStringArray(upsizedCheatField, ref cheatFieldStringArray);

      return cheatFieldStringArray;
    }

    internal static FieldDimensions DetermineMineFieldDimensions(string[] field)
    {
      var rows = field.Length;

      int cols;

      if (field.Length == 0)
        cols = 0;
      else
        cols = string.IsNullOrEmpty(field[0]) ? 0 : field[0].Length;
      
      return new FieldDimensions {Rows = rows, Cols = cols};
    }

    internal static FieldDimensions ResizeCheatFieldDimensions(FieldDimensions cheatFieldDimensions, int diffRows, int diffCols)
    {
      return new FieldDimensions
               {
                 Rows = cheatFieldDimensions.Rows + diffRows,
                 Cols = cheatFieldDimensions.Cols + diffCols
               };
    }
        
    internal static int[,] CreateEmptyCheatField(FieldDimensions cheatFieldDimensions)
    {
      var emptyField = new int[cheatFieldDimensions.Rows, cheatFieldDimensions.Cols];

      return emptyField;
    }

    internal static void AnalyzeMineField(string[] mineField, ref int[,] cheatField)
    {
      for (var row = 0; row < mineField.Length - 0; ++row)
      {
        var rowContent = mineField[row];
        AnalyzeMineFieldRow(rowContent, row, ref cheatField);
      }
    }

    internal static void AnalyzeMineFieldRow(string rowContent, int row, ref int[,] cheatField)
    {
      if (rowContent == null)
        return;

      for (var col = 0; col < rowContent.Length; ++col)
      {
        var mineFieldCell = rowContent[col];
        AnalyzeMineFieldCell(mineFieldCell, row, col, ref cheatField);
      }
    }

    internal static void AnalyzeMineFieldCell(char cellContent, int row, int col, ref int[,] cheatField)
    {
      if (cellContent == '*')
      {
        SetMineInCheatField(row + 1, col + 1, ref cheatField);
      }
    }

    internal static void SetMineInCheatField(int row, int col, ref int[,] cheatField)
    {
      cheatField[row - 1, col - 1]++; cheatField[row - 1, col    ]++; cheatField[row - 1, col + 1]++;
      cheatField[row    , col - 1]++;                                 cheatField[row    , col + 1]++;
      cheatField[row + 1, col - 1]++; cheatField[row + 1, col    ]++; cheatField[row + 1, col + 1]++;
    }

    internal static void TransformCheatFieldToStringArray(int[,] cheatField, ref string[] cheatFieldStringArray)
    {
      for (var row = 1; row < cheatField.GetLength(0) - 1; ++row)
      {
        TransformCheatFieldRowToString(cheatField, row, ref cheatFieldStringArray);
      }
    }

    internal static void TransformCheatFieldRowToString(int[,] cheatField, int row, ref string[] cheatFieldStringArray)
    {
      var rowStr = "";

      for (var col = 1; col < cheatField.GetLength(1) - 1; ++col )
      {
        rowStr += cheatField[row, col].ToString();
      }

      cheatFieldStringArray[row - 1] = rowStr;
    }
  }
}
